const util = require('util');
const Web3 = require('web3');
const utils = require('j7/utils');
const event = require('j7/event');
const sync = require("j7/sync");
const log = require("j7/log");
const bcutils = require("j7/bcutils");
const contract = require('common/contract');
const bcconst = require('common/bcconst');
const metaFactory = require('./metadata/factory');

class BlockChain {

  constructor(netId) {
    this.netId = netId;
  }

  async initInstance(user, address, jsonUrl) {
    const json = utils.readJsonFromFile(jsonUrl);
    return new this.web3.eth.Contract(
      json.abi,
      address,
      { from: user }
    );
  }

  async init() {
    this.web3Conf = metaFactory.getWeb3Conf(this.netId);
    this.contractsConf = metaFactory.getContractsConf(this.netId);
    this.netDir = metaFactory.getNetDir(this.netId);

    this.web3 = new Web3(this.getRpcUrl());
    this.web3.eth.handleRevert = true;
    this.web3.eth.accounts.wallet.add(this.getPrivateKey());
    for (const data of this.contractsConf) {
      this[`${data.name}Instance`] = await this.initInstance
      (this.getUserAddress(), data.address, this.netDir + data.json);
    }
    this.currencyHash = {};
    /*
    this.currencyHash['CEG'] = bcutils.toNormalAddress(
      this.getContractByName(contract.CEG_INSTANCE_NAME)['address']);
    if (this.netId == bcconst.ARBITRUM_NET_ID) {
      this.currencyHash['USDT'] = bcutils.toNormalAddress('0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9');
      this.currencyHash['USDC'] = bcutils.toNormalAddress('0xaf88d065e77c8cC2239327C5EDb3A432268e5831');
    } else if (this.netId == bcconst.ARBITRUM_TEST_NET_ID) {
      this.currencyHash['USDT'] = bcutils.toNormalAddress('0xaa34B79A0Ab433eaC900fB3CB9f191F5Cd27501D');
      this.currencyHash['USDC'] = bcutils.toNormalAddress('0x944D0A8463B2c955F90F7252bBb99A3395087155');
    }*/
    const chainId = await this.web3.eth.getChainId();
    if (chainId != this.netId) {
      log.warning(util.format('net id error %s %s',
                              chainId,
                              this.netId
                             ));
    }
    log.info(util.format('local.net_id:%s remote_net_id:%s',
                         this.netId,
                         chainId
                        ));
  }

  getNetId() {
    return this.netId;
  }

  getRpcUrl() {
    return this.web3Conf['block_server'];
  }

  getUserAddress() {
    return this.web3Conf['user_address'];
  }

  getPrivateKey() {
    return this.web3Conf['private_key'];
  }

  getContractByName(name) {
    let contract = null;
    this.contractsConf.forEach((item) => {
      if (item['name'] == name) {
        contract = item;
      }
    });
    return contract;
  }

  getNftAddress(tokenType) {
    const name = contract.getNftNameByTokenType(tokenType);
    const c = this.getContractByName(name);
    return c ? c['address'] : '';
  }

  isValidAddress(address) {
    return bcutils.isValidAddress(address);
  }

  getCurrencyAddressByName(currencyName) {
    return utils.hasKey(this.currencyHash, currencyName) ? this.currencyHash[currencyName] : '';
  }

}

module.exports = BlockChain;
